import os

from components.models import KubernetesManage
from general.deploy.deploy_conf_create import DeployConfCreate
from utils.Conf import Configuration
from utils.ssh_utils import SCPMet
from utils.views import ReturnClass
from general.deploy.dao import deploy_event_in

class DeployK8s():
    def __init__(self, host_info, kubernetes_manage_info):
        self.host_info = host_info
        self.kubernetes_manage_info = kubernetes_manage_info

    def set_ssh(self):
        self.ssh = SCPMet()
        self.ssh.set_info(self.host_info)
        self.ssh.cp_connect()

    def ssh_close(self):
        self.ssh.close()

    def go_cluster_conf(self):
        DeployConfCreate.ssh_echo_input(self.ssh, self.kubernetes_manage_info['conf_manage_ids'],
                                        self.kubernetes_manage_info['deploy_event_ids'])
        return True

    def host_file_dns(self, kubernetes_manage_hosts_info):

        exe_info = self.ssh.execcmd("hostnamectl set-hostname %s" %self.host_info['host_nick'])
        if not ReturnClass.if_ok(exe_info):
            deploy_event_in(self.kubernetes_manage_info['deploy_event_ids'],
                            'hostnamectl设置主机名失败',
                            '0')
            return False
        deploy_event_in(self.kubernetes_manage_info['deploy_event_ids'], 'hostnamectl设置主机名成功', '2')

        # 假如设置了controlPlaneEndpoint为域名，并且需要hosts解析
        if self.kubernetes_manage_info['control_plane_endpoint_ip']:
            kubernetes_manage_hosts_info.append({"host_ip": self.kubernetes_manage_info['control_plane_endpoint_ip'],
                                             "host_nick": self.kubernetes_manage_info['control_plane_endpoint']
                                             })

        for kubernetes_manage_hosts_info_one in kubernetes_manage_hosts_info:
            hosts_cmd = "sed -i '/%s/d' /etc/hosts; echo '%s %s' >> /etc/hosts" % (
            kubernetes_manage_hosts_info_one['host_nick'],
            kubernetes_manage_hosts_info_one['host_ip'],
            kubernetes_manage_hosts_info_one['host_nick']
            )
            self.ssh.execcmd(hosts_cmd)
            if not ReturnClass.if_ok(exe_info):
                deploy_event_in(self.kubernetes_manage_info['deploy_event_ids'],
                                '设置hosts条目失败（%s）' %hosts_cmd,
                                '0')
                return False
            deploy_event_in(self.kubernetes_manage_info['deploy_event_ids'], '设置hosts条目成功（%s）' %hosts_cmd, '2')

        return True

    def go_init_template(self):
        conf_obj = Configuration()
        BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
        kubeadm_init_yaml = os.path.join(os.path.dirname(BASE_DIR),
                                         'project_repository/soft_general/kubernetes/template/%s/%s/kubeadm-init.yaml' % (
                                         self.kubernetes_manage_info['kubernetes_versions'],
                                         self.kubernetes_manage_info['kubernetes_runtime']))

        kubeadm_init_yaml_text = conf_obj.get_file_text(kubeadm_init_yaml)
        kubeadm_init_yaml_text_complete = conf_obj.replace_text_parameter(kubeadm_init_yaml_text,
                                                                          {'host_ip': self.host_info['host_ip'],
                                                                           'host_nick': self.host_info['host_nick'],
                                                                           'vip': self.kubernetes_manage_info[
                                                                               'control_plane_endpoint'],
                                                                           'vip_port': self.kubernetes_manage_info[
                                                                               'control_plane_endpoint_port'],
                                                                           'service_subnet': self.kubernetes_manage_info[
                                                                               'service_subnet'],
                                                                           'pod_subnet': self.kubernetes_manage_info[
                                                                               'pod_subnet'],
                                                                           })

        DeployConfCreate.ssh_echo_input_template_text(self.ssh, kubeadm_init_yaml_text_complete,
                                                      '/tmp/kubeadm-init.yaml',
                                                      self.kubernetes_manage_info['deploy_event_ids'])

        for cmd in ["kubeadm config images pull --config /tmp/kubeadm-init.yaml", "kubeadm init --config /tmp/kubeadm-init.yaml"]:
            exe_info = self.ssh.execcmd(cmd)
            if not ReturnClass.if_ok(exe_info):
                deploy_event_in(self.kubernetes_manage_info['deploy_event_ids'],
                                '执行命令：%s失败(%s)' % (
                                cmd, exe_info['data']),
                                '0')
                return False

            deploy_event_in(self.kubernetes_manage_info['deploy_event_ids'],
                            '执行命令：%s成功' % (cmd), '2')

        return True

    def install_metrics_server(self):
        """
        安装metrics server服务
        @return:
        """
        BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
        metrics_server_yaml_path = os.path.join(os.path.dirname(BASE_DIR),
                                         'project_repository/soft_general/kubernetes/template/%s/metrics-server/components.yaml' % (
                                         self.kubernetes_manage_info['kubernetes_versions']))

        self.ssh.put_file(metrics_server_yaml_path, '/tmp/metrics_server.yaml')
        deploy_event_in(self.kubernetes_manage_info['deploy_event_ids'],
                        '上传：metrics_server.yaml文件成功' , '2')

        for cmd in ["kubeadm config images pull --config /tmp/metrics_server.yaml"]:
            exe_info = self.ssh.execcmd(cmd)
            if not ReturnClass.if_ok(exe_info):
                deploy_event_in(self.kubernetes_manage_info['deploy_event_ids'],
                                '执行命令：%s失败(%s)' % (
                                cmd, exe_info['data']),
                                '0')
                return False

            deploy_event_in(self.kubernetes_manage_info['deploy_event_ids'],
                            '执行命令：%s成功' % (cmd), '2')

        return True


    def host_action_execute(self, host_execute_infos, cmd_template_swap_value=None):
        if not cmd_template_swap_value:
            cmd_template_swap_value = {}

        conf_obj = Configuration()

        # 按权重排序执行命令
        host_execute_infos = sorted(host_execute_infos, key=lambda i: i['order_by'], reverse=True)

        # 按顺序执行命令
        for host_execute_info in host_execute_infos:

            #替换模板命令的模板内容
            host_action_execute_complete = conf_obj.replace_text_parameter(host_execute_info['system_content'],
                                                                              cmd_template_swap_value)

            command_result = self.ssh.execcmd(host_action_execute_complete)
            if ReturnClass.if_ok(command_result):
                deploy_event_in(self.kubernetes_manage_info['deploy_event_ids'],
                                '执行%s成功(%s)' % (
                                host_execute_info['system_action_name'], host_execute_info['system_content']), '2')
            else:
                other_info = ""
                if host_execute_info['ignore_error'] == 1:
                    other_info = "【被标记忽略的错误，跳过】"

                deploy_event_in(self.kubernetes_manage_info['deploy_event_ids'],
                                '执行%s失败(%s:%s%s)' % (
                                host_execute_info['system_action_name'], host_execute_info['system_content'],
                                command_result['data'], other_info), '0')

                if not other_info:
                    self.ssh_close()
                    return False
        return True

    def deploy_k8s_network_component(self):
        conf_obj = Configuration()
        BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
        network_component_text_name = "network_component.yaml"

        # 根据网络类型寻找配置文件
        network_component_init_yaml = os.path.join(os.path.dirname(BASE_DIR),
                                                   'project_repository/soft_general/kubernetes/template/%s/%s/network_component.yaml' % (
                                     self.kubernetes_manage_info['kubernetes_versions'],
                                     self.kubernetes_manage_info['network_component']))

        network_component_init_text = conf_obj.get_file_text(network_component_init_yaml)

        # 统一网络模块模板IP设置与集群设置一致
        network_component_init_text_complete = conf_obj.replace_text_parameter(network_component_init_text,
                                                                          {'network': self.kubernetes_manage_info[
                                                                              'pod_subnet'],
                                                                           })

        DeployConfCreate.save_file_ssh_put_file(self.ssh, network_component_init_text_complete,
                                                      '/tmp/%s' % network_component_text_name,
                                                      self.kubernetes_manage_info['deploy_event_ids'])

        for cmd in ["kubectl apply -f /tmp/%s" %network_component_text_name]:

            exe_info = self.ssh.execcmd(cmd)

            if not ReturnClass.if_ok(exe_info):
                deploy_event_in(self.kubernetes_manage_info['deploy_event_ids'],
                                '执行命令：%s返回状态异常(%s)' % (
                                    cmd, exe_info['data']),
                                '2')
                self.ssh_close()
                return False

            deploy_event_in(self.kubernetes_manage_info['deploy_event_ids'],
                            '执行命令：%s成功' % (cmd), '1')

        return True

    def node_get_and_set_kubeadm_token(self, master_host_connect_user_info):
        ssh_obj = SCPMet()
        ssh_obj.set_info(master_host_connect_user_info)
        ssh_obj.cp_connect()
        hosts_cmd = "kubeadm token create --print-join-command --ttl 0"
        exe_info = ssh_obj.execcmd(hosts_cmd)
        if not ReturnClass.if_ok(exe_info):
            deploy_event_in(self.kubernetes_manage_info['deploy_event_ids'],
                            '获取新token失败（%s）' % hosts_cmd,
                            '0')
            return False
        deploy_event_in(self.kubernetes_manage_info['deploy_event_ids'], '获取新token成功（%s）' % hosts_cmd, '2')
        token_now = exe_info['data']
        ssh_obj.close()

        hosts_cmd = token_now
        exe_info = self.ssh.execcmd(hosts_cmd)
        if not ReturnClass.if_ok(exe_info):
            deploy_event_in(self.kubernetes_manage_info['deploy_event_ids'],
                            'node加入集群失败（%s：%s）' % (hosts_cmd, exe_info['data']),
                            '0')
            return False
        deploy_event_in(self.kubernetes_manage_info['deploy_event_ids'], 'node加入集群成功（%s）' % hosts_cmd, '1')

        return True

    def master_get_and_set_kubeadm_token(self, master_host_connect_user_info):
        ssh_obj = SCPMet()
        ssh_obj.set_info(master_host_connect_user_info)
        ssh_obj.cp_connect()
        hosts_cmd = "echo $(kubeadm token create --print-join-command --ttl 0) --control-plane --certificate-key  $(kubeadm init phase upload-certs --upload-certs|tail -n 1)"
        exe_info = ssh_obj.execcmd(hosts_cmd)
        if not ReturnClass.if_ok(exe_info):
            deploy_event_in(self.kubernetes_manage_info['deploy_event_ids'],
                            '获取新token失败（%s）' % hosts_cmd,
                            '0')
            return False
        deploy_event_in(self.kubernetes_manage_info['deploy_event_ids'], '获取新token成功（%s）' % hosts_cmd, '2')
        token_now = exe_info['data']
        ssh_obj.close()

        hosts_cmd = token_now
        exe_info = self.ssh.execcmd(hosts_cmd)
        if not ReturnClass.if_ok(exe_info):
            deploy_event_in(self.kubernetes_manage_info['deploy_event_ids'],
                            'master加入集群失败（%s：%s）' % (hosts_cmd, exe_info['data']),
                            '0')
            return False
        deploy_event_in(self.kubernetes_manage_info['deploy_event_ids'], 'master加入集群成功（%s）' % hosts_cmd, '1')

        return True

    def help_delete_node(self, master_host_connect_user_info, help_quit_k8s_cmd):
        ssh_obj = SCPMet()
        ssh_obj.set_info(master_host_connect_user_info)
        ssh_obj.cp_connect()

        for host_execute_info in help_quit_k8s_cmd:
            command_result = ssh_obj.execcmd(host_execute_info['system_content'])
            if ReturnClass.if_ok(command_result):
                deploy_event_in(self.kubernetes_manage_info['deploy_event_ids'],
                                '执行%s成功(%s)' % (
                                host_execute_info['system_action_name'], host_execute_info['system_content']), '2')
            else:
                other_info = ""
                if host_execute_info['ignore_error'] == 1:
                    other_info = "【被标记忽略的错误，跳过】"

                deploy_event_in(self.kubernetes_manage_info['deploy_event_ids'],
                                '执行%s失败(%s:%s%s)' % (
                                host_execute_info['system_action_name'], host_execute_info['system_content'],
                                command_result['data'], other_info), '0')

                if not other_info:
                    self.ssh_close()
                    return False

        ssh_obj.close()

        return True